#include "app_buffer.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "log/log.h"


Buffer_t* app_buffer_init(int size)
{
    Buffer_t *Buffer = (Buffer_t*)malloc(sizeof(Buffer_t));

    Buffer->sub_buffer[0] = (Sub_buffer_t *)malloc(sizeof(Sub_buffer_t));
    Buffer->sub_buffer[1] = (Sub_buffer_t *)malloc(sizeof(Sub_buffer_t));

    Buffer->sub_buffer[0]->ptr = (char *)malloc(size);
    Buffer->sub_buffer[1]->ptr = (char *)malloc(size);

    Buffer->sub_buffer[0]->data_len = 0;
    Buffer->sub_buffer[1]->data_len = 0;
    
    Buffer->sub_buffer[0]->total_size = size;
    Buffer->sub_buffer[1]->total_size = size;

    pthread_mutex_init(&Buffer->read_lock, NULL);
    pthread_mutex_init(&Buffer->write_lock, NULL);

    return Buffer;
}

void app_buffer_destroy(Buffer_t *buffer)
{
    free(buffer->sub_buffer[0]->ptr);
    free(buffer->sub_buffer[1]->ptr);

    free(buffer->sub_buffer[0]);
    free(buffer->sub_buffer[1]);

    free(buffer);
}

int app_buffer_write(Buffer_t *buffer,char *data, int len)
{
    if(len > 255)
    {
        log_error("data len too long");
        return -1;
    }

    pthread_mutex_lock(&buffer->write_lock);
    log_debug("write lock");

    // 1. 选择写入的子缓冲区
    Sub_buffer_t *w_sub_buffer = buffer->sub_buffer[buffer->write_index];

    if(len > (w_sub_buffer->total_size - w_sub_buffer->data_len - 1))
    {
        log_error("memory not enough");
        pthread_mutex_unlock(&buffer->write_lock);
        log_debug("write unlock");
        return -1;
    }

    // 2. 写入数据
    w_sub_buffer->ptr[w_sub_buffer->data_len] = len;
    memcpy(w_sub_buffer->ptr + w_sub_buffer->data_len+1, data, len);
    w_sub_buffer->data_len += len + 1;


    pthread_mutex_unlock(&buffer->write_lock);
    log_debug("write unlock");
    return 0;
}

int app_buffer_read(Buffer_t *buffer,char *data_buf, int buf_size)
{

    pthread_mutex_lock(&buffer->read_lock);
    log_debug("read lock");

    // 1. 选择读取的子缓冲区
    Sub_buffer_t *r_sub_buffer = buffer->sub_buffer[buffer->read_index];

    if(r_sub_buffer->data_len == 0)
    {
        pthread_mutex_lock(&buffer->write_lock);
        log_debug("swap write lock"); // 写操作公用一把🔓，防止交换缓冲区时写操作被中断，也防止读操作被中断
        int temp = buffer->read_index;
        buffer->read_index = buffer->write_index;
        buffer->write_index = temp;
        r_sub_buffer = buffer->sub_buffer[buffer->read_index];
        pthread_mutex_unlock(&buffer->write_lock);
        log_debug("swap write unlock");

        if(r_sub_buffer->data_len == 0)
        {
            log_error("no data");
            return -1;
        }
    }

    // 2. 读取数据
    int len = r_sub_buffer->ptr[0];

    if(len > buf_size)
    {
        log_error("buf size too small");
        return -1;
    }

    memcpy(data_buf, r_sub_buffer->ptr+1, len);
    memmove(r_sub_buffer->ptr, r_sub_buffer->ptr+len+1, r_sub_buffer->data_len-len-1);

    pthread_mutex_unlock(&buffer->read_lock);
    log_debug("read unlock");

    return len;
}
